/*
 * $Id: arr.h,v 1.7 2006-02-07 07:23:30 bacon Exp $
 */

#ifndef _XP_BAS_ARR_H_
#define _XP_BAS_ARR_H_

#include <xp/types.h>
#include <xp/macros.h>

#define XP_ARR_BUF(x)  ((x)->buf)
#define XP_ARR_DATUM_SIZE(x) ((x)->datum_size)
#define XP_ARR_SIZE(x) ((x)->size)
#define XP_ARR_CAPA(x) ((x)->capa)

typedef struct xp_arr_t xp_arr_t;
typedef struct xp_arrcbs_t xp_arrcbs_t;

/* callback set */
struct xp_arrcbs_t
{
	void (*initarr)   (xp_arr_t* arr);
	void (*finiarr)   (xp_arr_t* arr);
	void (*initdatum) (xp_arr_t* arr, void* datum);
	void (*finidatum) (xp_arr_t* arr, void* datum);
	int  (*copydatum) (
		xp_arr_t* arr, const void* datum1, const void* datum2);
	int  (*compdatum) (
		xp_arr_t* arr, const void* datum1, const void* datum2);
	/*void (*adjust)   (xp_arr_t* arr, void* datum);*/
};

struct xp_arr_t 
{
	xp_byte_t*   buf;
	xp_size_t    datum_size;
	xp_size_t    size;     /* the number of datum */
	xp_size_t    capa; /* allocated size */
	xp_arrcbs_t* cbs;
	xp_bool_t    __dynamic;
};

#define XP_ARR_INVALID_INDEX (~(xp_size_t)0)
#define XP_ARR_SORT_ASCENDING  1
#define XP_ARR_SORT_DESCENDING 2

#ifdef __cplusplus
extern "C" {
#endif

/*
 * FUNCTION: xp_arr_open
 */
xp_arr_t* xp_arr_open (
	xp_arr_t* arr, xp_size_t capa, 
	xp_size_t datum_size, xp_arrcbs_t* cbs);

/*
 * FUNCTION: xp_arr_close
 */
void xp_arr_close (xp_arr_t* arr);

/*
 * FUNCTION: xp_arr_clear
 *   Clears the entire array.
 */
void xp_arr_clear (xp_arr_t* arr);

/*
 * FUNCTION: xp_arr_getsize
 */
xp_size_t xp_arr_getsize (xp_arr_t* arr);

/*
 * FUNCTION: xp_arr_setsize
 */
xp_arr_t* xp_arr_setsize (xp_arr_t* arr, xp_size_t capacity);

/*
 * FUNCTION: xp_arr_getcapa
 */
xp_size_t xp_arr_getcapa (xp_arr_t* arr);

/*
 * FUNCTION: xp_arr_setcapa
 */
xp_arr_t* xp_arr_setcapa (xp_arr_t* arr, xp_size_t capacity);

/* 
 * FUNCTION: xp_arr_getdatum
 *   returns the datum pointer at the given position.
 *   returns XP_NULL if index is out of bound.
 */
void* xp_arr_getdatum (xp_arr_t* arr, xp_size_t index);

/*
 * FUNCTION: xp_arr_putdatum:
 *   replaces the value at the given position by the value given.
 *   returns the datum pointer at the position "index" if successful.
 *   returns XP_NULL on failure.
 */
void* xp_arr_putdatum (xp_arr_t* arr, xp_size_t index, const void* value);

/*
 * xp_arr_insdatum:
 *   inserts the given value at the position denoted by "index". 
 *   resizes the arr if necessary.
 *   returns the value pointer on success, XP_NULL on failure.
 */
void* xp_arr_insdatum (
	xp_arr_t* arr, xp_size_t index, const void* value);

/* 
 * xp_arr_remrange:
 *   removes at most "count" data from the position "index".
 *   returns the number of data that have been removed.
 */
xp_size_t xp_arr_remrange (
	xp_arr_t* arr, xp_size_t index, xp_size_t count);

/* 
 * xp_arr_adddatum:
 *   inserts the given value into the end of an arr.
 *   returns the datum pointer on success, XP_NULL on failure.
 */
void* xp_arr_adddatum (xp_arr_t* arr, const void* value);

/* 
 * xp_arr_remdatum:
 *   removes the first datum matching the value given. 
 *   returns the number of data removed.
 */
xp_size_t xp_arr_remdatum (xp_arr_t* arr, const void* value);

/* 
 * xp_arr_remall:
 *   removes all data matching the value given.
 *   returns the number of data removed.
 */
xp_size_t xp_arr_remall (xp_arr_t* arr, const void* value);

/*
 * xp_arr_fill:
 *   fills at most "count" slots from "index" with the value.
 *   resizes the arr if necessary.
 *   returns the number of slots filled.
 */
xp_size_t xp_arr_fill (xp_arr_t* arr, 
	xp_size_t index, xp_size_t count, const void* value);

xp_size_t xp_arr_find (
	xp_arr_t* arr, const void* value, xp_size_t index);
xp_size_t xp_arr_rfind (
	xp_arr_t* arr, const void* value, xp_size_t index);

int xp_arr_sort (xp_arr_t* arr,
	xp_size_t index, xp_size_t count, int direction);

void* xp_arr_yield (
	xp_arr_t* arr, xp_size_t capacity, xp_size_t datum_size);

/*
 * xp_arr_walk:
 *   traverses the arr.
 *   moves forward or backward as returned by func.
 *   stops traversal if func returns 0 or when it hits beyond the bound.
 *   returns the number of datum visited.
 */
xp_size_t xp_arr_walk (
	xp_arr_t* arr, xp_size_t index, 
	xp_ssize_t (*func) (xp_arr_t*, xp_size_t, void*));

#ifdef __cplusplus
}
#endif

#endif
